package scatter.interview.rest.interview.i4_socket;
import java.io.IOException;
import java.net.InetSocketAddress;
import java.net.ServerSocket;
import java.nio.ByteBuffer;
import java.nio.channels.SelectableChannel;
import java.nio.channels.SelectionKey;
import java.nio.channels.Selector;
import java.nio.channels.ServerSocketChannel;
import java.nio.channels.SocketChannel;
import java.nio.charset.Charset;
import java.util.Iterator;
/**
 * Created by yangwei
 * Created at 2020/12/4 14:11
 */
public class SelectSocketServer {
    private static final int PORT = 8088;

    private ByteBuffer buffer = ByteBuffer.allocate(1024);

    public static void main(String[] args) throws IOException {

        SelectSocketServer ss = new SelectSocketServer();

        ss.go();
    }
    public String decode(ByteBuffer bb) {

        Charset charset = Charset.forName("utf-8");

        return charset.decode(bb).toString();

    }
    public void go() throws IOException {

        System.out.println("listening on port:" + PORT);

        ServerSocketChannel ssc = ServerSocketChannel.open();

        ServerSocket ss = ssc.socket();

        Selector selector = Selector.open();

        ss.bind(new InetSocketAddress(PORT));

        ssc.configureBlocking(false);

        ssc.register(selector, SelectionKey.OP_ACCEPT);

        while (true) {
            int n = selector.select();

            if (n == 0) {
                continue;
            }

            Iterator<SelectionKey> iter = selector.selectedKeys().iterator();

            while (iter.hasNext()) {
                SelectionKey key = iter.next();
                if (key.isAcceptable()) {
                    ServerSocketChannel server = (ServerSocketChannel) key
                            .channel();
                    SocketChannel client = server.accept();
                    register(selector, client, SelectionKey.OP_READ);
                    System.out.println("Accept client:" + client);
                    acceptClient(client);
                }
                if (key.isReadable()) {
                    readData(key);
                }
                iter.remove();
            }
        }
    }

    protected void register(Selector selector, SelectableChannel channel,
                            int ops) throws IOException {
        if (channel == null) {
            return;
        }
        channel.configureBlocking(false);

        channel.register(selector, ops);

    }

    protected void readData(SelectionKey key) throws IOException {
        //System.out.println("readData");
        SocketChannel socketChannel = (SocketChannel) key.channel();
        int count;
        while ((count = socketChannel.read(buffer)) > 0) {
            System.out.println(decode(buffer));
            buffer.flip();

            while (buffer.hasRemaining()) {
                socketChannel.write(buffer);
            }

            buffer.clear();

            if (count < 0) {
                socketChannel.close();
            }
        }
    }

    private void acceptClient(SocketChannel channel) throws IOException {
        System.out.println("acceptClient");
        buffer.clear();
        buffer.put("you have already connected server!".getBytes());
        buffer.flip();

        channel.write(buffer);
    }
}
